package de.dhbw.horb.inf2013.vierFarbenProblem.model;

import java.awt.Color;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.AdjacencyListGraph;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.ColoredVertex;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.Graph;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.NoColorSetException;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.SolverListenerInterface;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.VertexNotSetException;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelListenerInterface;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.solver.BacktrackingIterativFourColorSolver;
import de.dhbw.horb.inf2013.vierFarbenProblem.model.solver.FourColorSolver;

/**
 * The Class Model.
 */
public class Model implements ModelInterface, SolverListenerInterface {

	/** The solver. */
	private FourColorSolver solver;

	/** The graph. */
	protected Graph graph;

	/** The listeners. */
	private List<ModelListenerInterface> listeners = new LinkedList<ModelListenerInterface>();

	/** The solver thread. */
	private Thread solverThread;

	/**
	 * Instantiates a new model.
	 */
	public Model() {
		this.solver = new BacktrackingIterativFourColorSolver();
		solver.addSolverListener(this);

		solver.addColor(new Color(57, 212, 57));
		solver.addColor(new Color(51, 59, 202));
		solver.addColor(new Color(212, 203, 57));
		solver.addColor(new Color(202, 51, 52));

		this.graph = new AdjacencyListGraph();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface
	 * #addVertex
	 * (de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.ColoredVertex)
	 */
	@Override
	public void addVertex(ColoredVertex vertex) {
		graph.addVertex(vertex);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface
	 * #addEdge(int, int)
	 */
	@Override
	public void addEdge(int vertex1, int vertex2) {
		try {
			graph.addEdge(vertex1, vertex2);
		} catch (VertexNotSetException e) {
			System.out.println(vertex1 + vertex2);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface
	 * #getColor(int)
	 */
	@Override
	public Color getColor(int id) {
		Color color = null;
		try {
			color = graph.getVertex(id).getColor();
		} catch (NoColorSetException e) {

		} catch (VertexNotSetException e) {

		}
		return color;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface
	 * #resetAll()
	 */
	@Override
	public void resetAll() {
		if (solverThread != null) {
			solverThread.stop();
		}

		graph.resetAll();
		graph = new AdjacencyListGraph();
		notifyModelListener();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface
	 * #start()
	 */
	@Override
	public void start() {
		solver.setGraph(graph);
		solverThread = new Thread(solver);
		solverThread.start();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.ModelInterface
	 * #addModelListener
	 * (de.dhbw.horb.inf2013.vierFarbenProblem.model.interfaces.
	 * ModelListenerInterface)
	 */
	@Override
	public void addModelListener(ModelListenerInterface modelListener) {
		listeners.add(modelListener);
	}

	/**
	 * Notify model listener.
	 */
	public void notifyModelListener() {
		Iterator<ModelListenerInterface> iterator = listeners.iterator();
		while (iterator.hasNext()) {
			iterator.next().update();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see de.dhbw.horb.inf2013.vierFarbenProblem.model.datatypes.
	 * SolverListenerInterface#update()
	 */
	@Override
	public void update() {
		notifyModelListener();
	}

}
